﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace project_forgotten_tuba
{
    public class GameServer
    {
        public Container MainContainer { get; set; }

        private NetServer _mainServer;

        public int GetConnectionCount()
        {
            return _mainServer.Connections.Count();
        }

        public void Init()
        {
            _mainServer = new NetServer(GameServerConfig());
            _mainServer.Start();
        }

        public NetPeerConfiguration GameServerConfig()
        {
            int _SERVERPORT_ = 14242;

            NetPeerConfiguration serverConfig = new NetPeerConfiguration("gameConfig");
            serverConfig.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
            serverConfig.Port = _SERVERPORT_;
            serverConfig.PingInterval = 0.5f;
            serverConfig.ConnectionTimeout = 2.0f;
            serverConfig.MaximumTransmissionUnit = 1200;

            return serverConfig;
        }

        public void HandleAllMessages()
        {
            NetIncomingMessage msg;
            while ((msg = _mainServer.ReadMessage()) != null)
            {
                switch (msg.MessageType)
                {
                    case NetIncomingMessageType.ConnectionApproval:
                        HandleConnectionApproval(msg);
                        break;
                    case NetIncomingMessageType.StatusChanged:
                        HandleStatusChanged(msg);
                        break;
                    case NetIncomingMessageType.Data:
                        HandleDataMessage(msg);
                        break;
                    case NetIncomingMessageType.ErrorMessage:
                        break;
                    case NetIncomingMessageType.WarningMessage:
                        break;
                    default:
                        break;
                }
                _mainServer.Recycle(msg);
            }

        }

        public void HandleConnectionApproval(NetIncomingMessage msg)
        {
            if (_mainServer.Connections.Count < 10)
            {
                msg.SenderConnection.Approve();
            }
            else
            {
                msg.SenderConnection.Deny();
            }
        }
        public void HandleStatusChanged(NetIncomingMessage msg)
        {
            byte statusByte = msg.ReadByte();
            switch (statusByte)
            {
                case (byte)NetConnectionStatus.Disconnected:
                    break;
                case (byte)NetConnectionStatus.Connected:
                    SendDeckRequest();
                    break;
                default:
                    break;
            }
        }

        public void HandleDataMessage(NetIncomingMessage msg)
        {
            GameMessage.Type msgTypeByte = (GameMessage.Type)msg.ReadByte();
            switch (msgTypeByte)
            {
                case GameMessage.Type.PlayerInput:
                    HandleDataPlayerInputMessage(msg);
                    break;
                case GameMessage.Type.Deck:
                    HandleDataDeckMessage(msg);
                    break;
            }

        }


        public void HandleDataPlayerInputMessage(NetIncomingMessage msg)
        {
            int playerindex = msg.ReadInt32();
            int actiontype = msg.ReadInt32(); 
            int c = msg.ReadInt32();
            int r = msg.ReadInt32();

            //MainContainer.ServerGameState.PerformInput(playerindex, (Container.InputType)actiontype, c, r);

            NetOutgoingMessage inputmsg = _mainServer.CreateMessage();
            inputmsg.Write((byte)GameMessage.Type.PlayerInput);
            inputmsg.Write(playerindex);
            inputmsg.Write(actiontype);
            inputmsg.Write(c);
            inputmsg.Write(r);

            
            _mainServer.SendMessage(inputmsg, _mainServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
        }
        public void HandleDataDeckMessage(NetIncomingMessage msg)
        {
            int playerindex = msg.ReadInt32();

            int numbytes = msg.ReadInt32();
            byte[] serializeddeck = msg.ReadBytes(numbytes);
            List<string> deck = BinarySerializer.DeserializeFromByteArray<List<string>>(serializeddeck);

            //MainContainer.ServerGameState.LoadStringListAsCards(deck, playerindex);
            //SendSerializedStateMessage();

            NetOutgoingMessage deckmsg = _mainServer.CreateMessage();
            deckmsg.Write((byte)GameMessage.Type.Deck);
            deckmsg.Write(playerindex);
            deckmsg.Write(numbytes);
            deckmsg.Write(serializeddeck);

            if (_mainServer.Connections.Count > 0)
                _mainServer.SendMessage(deckmsg, _mainServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
        }

        /*
        public void SendSerializedStateMessage(NetConnection recipient = null)
        {
            byte[] binaryserializedstate;

            MainContainer.ServerGameState.MainContainer = null;
            binaryserializedstate = BinarySerializer.SerializeToByteArray<GameState>(MainContainer.ServerGameState);
            MainContainer.ServerGameState.MainContainer = this.MainContainer;

            byte[] compressedbinarystate = ByteArrayCompressor.Compress(binaryserializedstate);



            NetOutgoingMessage statemsg = _mainServer.CreateMessage();
            statemsg.Write((byte)GameMessage.Type.State);
            statemsg.Write((int)compressedbinarystate.Length);
            statemsg.Write(compressedbinarystate);

            if(recipient != null)
                _mainServer.SendMessage(statemsg, recipient, NetDeliveryMethod.ReliableOrdered, 0);
            else if(_mainServer.Connections.Count > 0)
                _mainServer.SendMessage(statemsg, _mainServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
            
        }*/
        public void SendDeckRequest(NetConnection recipient = null)
        {
            NetOutgoingMessage deckrequestmsg = _mainServer.CreateMessage();
            deckrequestmsg.Write((byte)GameMessage.Type.DeckRequest);

            if (recipient != null) _mainServer.SendMessage(deckrequestmsg, recipient, NetDeliveryMethod.ReliableOrdered);
            else if (_mainServer.Connections.Count > 0)
                _mainServer.SendMessage(deckrequestmsg, _mainServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
        }

    }
}
